package cn.xshi.bpm.design;

import cn.hutool.core.collection.CollectionUtil;
import com.mxgraph.canvas.mxGraphicsCanvas2D;
import com.mxgraph.canvas.mxICanvas2D;
import com.mxgraph.reader.mxSaxOutputHandler;
import com.mxgraph.util.mxUtils;
import cn.xshi.common.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.StringReader;
import java.util.Hashtable;
import java.util.List;
/**
 * @Desc 导出图片格式为PNG
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Slf4j
public class MxGraphToBase64 {
	private transient SAXParserFactory parserFactory = SAXParserFactory.newInstance();
	private transient Hashtable<String, Image> imageCache = new Hashtable<String, Image>();

	/**
	 * 使用xmlimg生成Base64流
	 * @param url
	 * @param imgxml
	 * @param w
	 * @param h
	 * @param response
	 * @return
	 */
	public BufferedImage imageXmlBase64(String url,String imgxml,String w,String h,HttpServletResponse response){
		try{
//			imgxml = URLDecoder.decode(imgxml, "UTF-8");
			return handleRequest(url,imgxml,w,h,response);
		}catch (Exception e) {
			log.error("Mxgraph 导出Image Base64异常：{}",e);
		}
		return null;
	}

	/**
	 * 创建并返回请求的图片
	 * @return
	 * @throws SAXException
	 * @throws ParserConfigurationException
	 * @throws IOException
	 */
	protected void parseXmlSax(String xml, mxICanvas2D canvas){
		mxSaxOutputHandler handler = new mxSaxOutputHandler(canvas);
		XMLReader reader;
		try{
			reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
			reader.setContentHandler(handler);
			reader.parse(new InputSource(new StringReader(xml)));
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	protected BufferedImage handleRequest(String url,String imgxml,String width,String height,HttpServletResponse response) throws Exception{
		int w = Integer.parseInt(width);
		int h = Integer.parseInt(height);
		if(w > 0 && h > 0 && imgxml != null && imgxml.length() > 0){
			Color bg = Color.WHITE;
			return writeImage(url, w, h, bg, imgxml, response);
		}
		return null;
	}

	protected BufferedImage writeImage(String url, int w, int h, Color bg, String xml, HttpServletResponse response)
			throws IOException, SAXException, ParserConfigurationException{
		BufferedImage image = mxUtils.createBufferedImage(w, h, bg);
		if(image != null){
//			Font font = new Font("楷体", Font.BOLD, 12);
//			Font font = new Font("楷体", Font.ITALIC, 12);
			Graphics2D g2 = image.createGraphics();
			Font font = new Font("宋体",g2.getFont().getStyle(),g2.getFont().getSize());
			g2.setFont(font);
//			g2.setFont(font);
			g2.setColor(Color.WHITE);//图片背景颜色
			mxUtils.setAntiAlias(g2, true, true);
			renderXml(xml, createCanvas(url, g2));
		}
		return image;
	}

	protected void renderXml(String xml, mxICanvas2D canvas) throws SAXException, ParserConfigurationException, IOException{
		XMLReader reader = parserFactory.newSAXParser().getXMLReader();
		reader.setContentHandler(new mxSaxOutputHandler(canvas));
		reader.parse(new InputSource(new StringReader(xml)));
	}

	protected mxGraphicsCanvas2D createCanvas(String url, Graphics2D g2){
		final Hashtable<String, Image> shortCache = new Hashtable<String, Image>();
		final String domain = url.substring(0, url.lastIndexOf("/"));
		mxGraphicsCanvas2D g2c = new mxGraphicsCanvas2D(g2){
			//解决乱码（重写）
			@Override
			protected Font createFont(String family, int style, int size) {
				return super.createFont("宋体", style, size);
			}
			public Image loadImage(String src){
				Hashtable<String, Image> cache = shortCache;
				if(src.startsWith(domain)){
					cache = imageCache;
				}
				Image image = cache.get(src);
				if(image == null){
					image = super.loadImage(src);
					if(image != null){
						cache.put(src, image);
					}else{
						cache.put(src, null);
					}
				}
				return image;
			}
		};
		return g2c;
	}

	/**
	 *  根据节点id重新设置imgXml 用于高亮
	 * @param imgXml
	 * @param id
	 */
	public ImgXmlEntity doImgXml(String imgXml,String id){
		ImgXmlEntity imgXmlEntity = new ImgXmlEntity();
		if(StringUtil.isEmpty(imgXml)){
			return imgXmlEntity;
		}
		if(StringUtil.isEmpty(id)){
			return imgXmlEntity;
		}
		doElement(imgXml,id,imgXmlEntity);
		return imgXmlEntity;
	}

	/**
	 *  根据节点id重新设置imgXml 用于高亮
	 * @param imgXml
	 * @param idList
	 */
	public ImgXmlEntity doImgXml(String imgXml,List<String> idList){
		ImgXmlEntity imgXmlEntity = new ImgXmlEntity();
		if(StringUtil.isEmpty(imgXml)){
			return imgXmlEntity;
		}
		if(CollectionUtil.isEmpty(idList)){
			return imgXmlEntity;
		}
		doMultiElement(imgXml,idList,imgXmlEntity);
		return imgXmlEntity;
	}

	/**
	 *
	 * @param imgXml
	 * @param id
	 * @return
	 */
	public void doElement(String imgXml,String id,ImgXmlEntity imgXmlEntity){
		try {
			//去除头部结束||...............................
			InputSource in = new InputSource(new StringReader(imgXml));
			in.setEncoding("UTF-8");
			SAXReader reader = new SAXReader();
			Document document;
			document = DocumentHelper.parseText(imgXml);
			document = reader.read(in);
			//获取根节点
			Element root = document.getRootElement();
			List<Element> mxCellList = root.elements("gradient");
			List<Element> rectCellList = root.elements("rect");
			for(int i = 0; i < mxCellList.size(); i++){
				Element element = (Element) mxCellList.get(i);
				if(null != element && !StringUtil.isEmpty(element.attributeValue("strokecolorNodeID")) && element.attributeValue("strokecolorNodeID").equals(id)){
					mxCellList.get(i).attribute("c1").setValue("#34bfa3");
					mxCellList.get(i).attribute("c2").setValue("#fff");
				}
			}
			for(int i = 0; i < rectCellList.size(); i++){
				Element element = (Element) rectCellList.get(i);
				if(null != element && !StringUtil.isEmpty(element.attributeValue("rectNodeID")) && element.attributeValue("rectNodeID").equals(id)){
					imgXmlEntity.setX(element.attributeValue("x"));
					imgXmlEntity.setY(element.attributeValue("y"));
					imgXmlEntity.setW(element.attributeValue("w"));
					imgXmlEntity.setH(element.attributeValue("h"));
				}
			}
			imgXmlEntity.setImgXml(root.asXML());
		}catch (Exception e){
			log.error("查找ImgXml节点异常：",e);
		}
	}

	/**
	 *
	 * @param imgXml
	 * @param idList
	 * @return
	 */
	public void doMultiElement(String imgXml,List<String> idList,ImgXmlEntity imgXmlEntity){
		try {
			//去除头部结束||...............................
			InputSource in = new InputSource(new StringReader(imgXml));
			in.setEncoding("UTF-8");
			SAXReader reader = new SAXReader();
			Document document;
			document = DocumentHelper.parseText(imgXml);
			document = reader.read(in);
			//获取根节点
			Element root = document.getRootElement();
			List<Element> mxCellList = root.elements("gradient");
			List<Element> rectCellList = root.elements("rect");
			for(int i = 0; i < mxCellList.size(); i++){
				Element element = (Element) mxCellList.get(i);
				for(String id: idList){
					if(null != element && !StringUtil.isEmpty(element.attributeValue("strokecolorNodeID")) && element.attributeValue("strokecolorNodeID").equals(id)){
						mxCellList.get(i).attribute("c1").setValue("#34bfa3");
						mxCellList.get(i).attribute("c2").setValue("#fff");
					}
				}

			}
			for(int i = 0; i < rectCellList.size(); i++){
				Element element = (Element) rectCellList.get(i);
				for(String id: idList){
					if(null != element && !StringUtil.isEmpty(element.attributeValue("rectNodeID")) && element.attributeValue("rectNodeID").equals(id)){
						imgXmlEntity.setX(element.attributeValue("x"));
						imgXmlEntity.setY(element.attributeValue("y"));
						imgXmlEntity.setW(element.attributeValue("w"));
						imgXmlEntity.setH(element.attributeValue("h"));
					}
				}
			}
			imgXmlEntity.setImgXml(root.asXML());
		}catch (Exception e){
			log.error("查找ImgXml节点异常：",e);
		}
	}
}
